use std::fs::OpenOptions;
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

// 共享内存的大小
const SHM_SIZE: usize = 1024;
// 共享内存标识符
const SHM_NAME: &str = "shm_example";

// 消息结构
#[repr(C)]
struct Message {
    written: AtomicBool, // 作为一个标志，非0：表示可读，0 ：表示可写
    text: [u8; SHM_SIZE - std::mem::size_of::<AtomicBool>()], // 实际消息数据
}

// 服务端代码：
fn server(shm: &Message) {
    let stdin = io::stdin();
    let mut buffer = String::new();

    loop {
        // 读取共享内存
        if shm.written.load(Ordering::SeqCst) {
            println!("Server received: {}", String::from_utf8_lossy(&shm.text));
            shm.written.store(false, Ordering::SeqCst); // 设置共享内存为可写状态
        }

        // 使用标准输入作为事件
        let _ = stdin.read_line(&mut buffer);
    }
}

// 客户端代码：
fn client(shm: &Message) {
    let stdin = io::stdin();
    let mut buffer = String::new();

    loop {
        while shm.written.load(Ordering::SeqCst) {
            thread::sleep(Duration::from_secs(1)); // 等待服务器读取消息
        }

        print!("Enter some text: ");
        io::stdout().flush().unwrap();
        let _ = stdin.read_line(&mut buffer);

        shm.text[..buffer.len()].copy_from_slice(buffer.as_bytes());
        shm.written.store(true, Ordering::SeqCst); // 更新标志，标识已写入数据
        buffer.clear();
    }
}

fn main() -> io::Result<()> {
    // 创建或打开共享内存对象
    let shm_fd = OpenOptions::new()
        .create(true)
        .read(true)
        .write(true)
        .open(SHM_NAME)?;

    // 设置共享内存大小
    unsafe {
        ftruncate(shm_fd.into_raw_fd(), std::mem::size_of::<Message>())?;
    }

    // 将共享内存映射到进程地址空间
    let shm = unsafe {
        mmap(
            std::ptr::null_mut(),
            std::mem::size_of::<Message>(),
            PROT_READ | PROT_WRITE,
            MAP_SHARED,
            shm_fd.into_raw_fd(),
            0,
        )
    }
    ?;

    shm.written.store(false, Ordering::SeqCst);

    let pid = thread::spawn(move || {
        // 子进程 - 客户端
        client(&shm);
    });

    // 父进程 - 服务器
    server(&shm);

    // 断开共享内存映射
    unsafe {
        munmap(shm as *mut Message, std::mem::size_of::<Message>())?;
    }

    // 删除共享内存对象
    unsafe {
        shm_unlink(SHM_NAME.as_ptr())?;
    }

    Ok(())
}
